#include <stdlib.h>
#include <string.h>
#include "queue.h"

// 初始化队列
int queue_init(queue_t **pq, int capacity, int elem_size) {
    // 检查参数有效性（容量>0，元素大小>0，队列指针非空）
    if (pq == NULL || capacity <= 0 || elem_size <= 0) {
        return 0;
    }

    // 分配队列结构体内存
    *pq = (queue_t *)malloc(sizeof(queue_t));
    if (*pq == NULL) {
        return 0;
    }

    // 分配数据缓冲区（容量 * 单个元素大小）
    (*pq)->data = malloc(capacity * elem_size);
    if ((*pq)->data == NULL) {
        free(*pq);  // 缓冲区分配失败，释放队列结构体
        *pq = NULL;
        return 0;
    }

    // 初始化队列状态
    (*pq)->head = 0;
    (*pq)->tail = 0;
    (*pq)->capacity = capacity;
    (*pq)->elem_size = elem_size;

    return 1;
}

// 队列空判断
int queue_is_empty(const queue_t *pq) {
    if (pq == NULL) {
        return 1;  // 空指针视为空队列（避免非法访问）
    }
    return (pq->head == pq->tail) ? 1 : 0;
}

// 队列满判断（循环队列：(tail+1) % capacity == head 表示满）
int queue_is_full(const queue_t *pq) {
    if (pq == NULL) {
        return 0;  // 空指针视为非满队列
    }
    return ((pq->tail + 1) % pq->capacity == pq->head) ? 1 : 0;
}

// 入队列（拷贝data到缓冲区，避免浅拷贝问题）
int queue_enq(queue_t *pq, const void *data) {
    if (pq == NULL || data == NULL || queue_is_full(pq)) {
        return 0;
    }

    // 计算当前队尾元素的地址，拷贝数据（按元素大小拷贝）
    void *dest = (char *)pq->data + (pq->tail * pq->elem_size);
    memcpy(dest, data, pq->elem_size);

    // 队尾指针后移（循环处理）
    pq->tail = (pq->tail + 1) % pq->capacity;

    return 1;
}

// 出队列（从缓冲区拷贝数据到data）
int queue_deq(queue_t *pq, void *data) {
    if (pq == NULL || data == NULL || queue_is_empty(pq)) {
        return 0;
    }

    // 计算当前队头元素的地址，拷贝数据
    void *src = (char *)pq->data + (pq->head * pq->elem_size);
    memcpy(data, src, pq->elem_size);

    // 队头指针后移（循环处理）
    pq->head = (pq->head + 1) % pq->capacity;

    return 1;
}

// 销毁队列（先释放缓冲区，再释放队列结构体）
void queue_destory(queue_t **pq) {
    if (pq != NULL && *pq != NULL) {
        free((*pq)->data);  // 释放数据缓冲区
        free(*pq);          // 释放队列结构体
        *pq = NULL;         // 置空，避免野指针
    }
}